package com.xuzhiguang.baidu.pan.sdk.operations;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JavaType;
import com.xuzhiguang.baidu.pan.sdk.common.http.HttpClient;
import com.xuzhiguang.baidu.pan.sdk.configuration.BaiduPanConfiguration;
import com.xuzhiguang.baidu.pan.sdk.exception.BaiduPanSdkException;
import com.xuzhiguang.baidu.pan.sdk.model.*;
import com.xuzhiguang.baidu.pan.sdk.token.ITokenStorage;
import org.apache.commons.lang3.StringUtils;

import java.util.LinkedHashMap;
import java.util.Map;

/**
 * @author xuzhiguang
 * @date 2020/6/26 12:54
 */
public class BaiduPanBasicOperations extends BaiduPanOperations {

    public BaiduPanBasicOperations(HttpClient httpClient, ITokenStorage tokenStorage, BaiduPanConfiguration baiduPanConfiguration) {
        super(httpClient, tokenStorage, baiduPanConfiguration);
    }

    /**
     * https://pan.baidu.com/union/document/basic#获取用户信息
     * 获取用户信息
     * @return
     */
    public BasicUserInfoResult userInfo() throws BaiduPanSdkException {
        String url = this.baiduPanApiUrlPrefix + "/xpan/nas";
        Map<String, String> parameters = new LinkedHashMap<>(1);
        parameters.put("method", "uinfo");

        JavaType javaType = this.objectMapper.constructType(BasicUserInfoResult.class);

        return this.get(url, parameters, null, true, javaType);
    }

    /**
     * https://pan.baidu.com/union/document/basic#获取网盘容量信息
     * 获取网盘容量信息
     * @return
     * @throws BaiduPanSdkException
     */
    public BasicQuotaResult quota() throws BaiduPanSdkException {
        return this.quota(null, null);
    }

    /**
     * https://pan.baidu.com/union/document/basic#获取网盘容量信息
     * 获取网盘容量信息
     * @param checkFree 检查免费信息
     * @param checkExpire 检查过期信息
     * @return
     * @throws BaiduPanSdkException
     */
    public BasicQuotaResult quota(Boolean checkFree, Boolean checkExpire) throws BaiduPanSdkException {

        String url = " https://pan.baidu.com/api/quota";
        Map<String, String> parameters = new LinkedHashMap<>(2);

        if (checkFree != null && checkFree) {
            parameters.put("checkfree", "1");
        }

        if (checkExpire != null && checkExpire) {
            parameters.put("checkexpire", "1");
        }

        JavaType javaType = this.objectMapper.constructType(BasicQuotaResult.class);
        return this.get(url, parameters, null, true, javaType);
    }

    /**
     * https://pan.baidu.com/union/document/basic#获取用户信息
     * 获取用户信息
     * @param params
     * @return
     */
    public BasicFileListResult fileList(BasicFileListParams params) throws BaiduPanSdkException {

        String url = this.baiduPanApiUrlPrefix + "/xpan/file";
        Map<String, String> parameters = new LinkedHashMap<>();
        parameters.put("method", "list");

        parameters.putAll(beanToMap(params));

        JavaType javaType = this.objectMapper.constructType(BasicFileListResult.class);
        return this.get(url, parameters, null, true, javaType);
    }

    /**
     * https://pan.baidu.com/union/document/basic#递归获取文件列表
     * 递归获取文件列表
     * @param params
     * @return
     * @throws BaiduPanSdkException
     */
    public BasicFileListAllResult fileListAll(BasicFileListAllParams params) throws BaiduPanSdkException {

        String url = this.baiduPanApiUrlPrefix + "/xpan/multimedia";
        Map<String, String> parameters = new LinkedHashMap<>();
        parameters.put("method", "listall");

        if (params.getPath() == null) {
            throw new IllegalArgumentException("参数 path 不能为空");
        }

        parameters.putAll(beanToMap(params));

        JavaType javaType = this.objectMapper.constructType(BasicFileListAllResult.class);
        return this.get(url, parameters, null, true, javaType);
    }

    /**
     * https://pan.baidu.com/union/document/basic#获取文档列表
     * 获取文档列表
     * @param params
     * @return
     * @throws BaiduPanSdkException
     */
    public BasicDocListResult docList(BasicDocListParams params) throws BaiduPanSdkException {
        String url = this.baiduPanApiUrlPrefix + "/xpan/file";
        Map<String, String> parameters = new LinkedHashMap<>();
        parameters.put("method", "doclist");

        parameters.putAll(beanToMap(params));

        JavaType javaType = this.objectMapper.constructType(BasicDocListResult.class);
        return this.get(url, parameters, null, true, javaType);
    }

    /**
     * https://pan.baidu.com/union/document/basic#获取文档列表
     * 获取图片列表
     * @param params
     * @return
     * @throws BaiduPanSdkException
     */
    public BasicImageListResult imageList(BasicImageListParams params) throws BaiduPanSdkException {

        String url = this.baiduPanApiUrlPrefix + "/xpan/file";
        Map<String, String> parameters = new LinkedHashMap<>();
        parameters.put("method", "imagelist");

        parameters.putAll(beanToMap(params));

        JavaType javaType = this.objectMapper.constructType(BasicImageListResult.class);
        return this.get(url, parameters, null, true, javaType);
    }

    /**
     * https://pan.baidu.com/union/document/basic#获取视频列表
     * 获取视频列表
     * @param params
     * @return
     * @throws BaiduPanSdkException
     */
    public BasicVideoListResult videoList(BasicVideoListParams params) throws BaiduPanSdkException {
        String url = this.baiduPanApiUrlPrefix + "/xpan/file";
        Map<String, String> parameters = new LinkedHashMap<>();
        parameters.put("method", "videolist");

        parameters.putAll(beanToMap(params));

        JavaType javaType = this.objectMapper.constructType(BasicVideoListResult.class);
        return this.get(url, parameters, null, true, javaType);
    }

    /**
     * https://pan.baidu.com/union/document/basic#获取bt列表
     * 获取bt列表
     * @param params
     * @return
     * @throws BaiduPanSdkException
     */
    public BasicBtListResult btList(BasicBtListParams params) throws BaiduPanSdkException {
        String url = this.baiduPanApiUrlPrefix + "/xpan/file";
        Map<String, String> parameters = new LinkedHashMap<>();
        parameters.put("method", "btlist");

        parameters.putAll(beanToMap(params));

        JavaType javaType = this.objectMapper.constructType(BasicBtListResult.class);
        return this.get(url, parameters, null, true, javaType);
    }

    /**
     * https://pan.baidu.com/union/document/basic#获取分类列表文件
     * 获取分类文件总个数
     * @param params
     * @return
     * @throws BaiduPanSdkException
     */
    public BasicCategoryInfoResult categoryInfo(BasicCategoryInfoParams params) throws BaiduPanSdkException {
        String url = "https://pan.baidu.com/api/categoryinfo";
        Map<String, String> parameters = new LinkedHashMap<>();

        if (params.getCategory() == null) {
            throw new IllegalArgumentException("参数 category 不能为空");
        }

        parameters.putAll(beanToMap(params));

        JavaType javaType = this.objectMapper.constructType(BasicCategoryInfoResult.class);
        return this.get(url, parameters, null, true, javaType);
    }

    /**
     * https://pan.baidu.com/union/document/basic#获取分类列表文件
     * 获取分类列表文件
     * @param params
     * @return
     * @throws BaiduPanSdkException
     */
    public BasicCategoryListResult categoryList(BasicCategoryListParams params) throws BaiduPanSdkException {
        String url = this.baiduPanApiUrlPrefix + "/xpan/multimedia";
        Map<String, String> parameters = new LinkedHashMap<>();
        parameters.put("method", "categorylist");

        if (params.getCategory() == null) {
            throw new IllegalArgumentException("参数 category 不能为空");
        }

        parameters.putAll(beanToMap(params));

        JavaType javaType = this.objectMapper.constructType(BasicCategoryListResult.class);
        return this.get(url, parameters, null, true, javaType);
    }

    /**
     * https://pan.baidu.com/union/document/basic#搜索文件
     * 搜索文件
     * @param params
     * @return
     * @throws BaiduPanSdkException
     */
    public BasicFileSearchResult fileSearch(BasicFileSearchParams params) throws BaiduPanSdkException {
        String url = this.baiduPanApiUrlPrefix + "/xpan/file";
        Map<String, String> parameters = new LinkedHashMap<>();
        parameters.put("method", "search");

        if (params.getKey() == null) {
            throw new IllegalArgumentException("参数 key 不能为空");
        }

        parameters.putAll(beanToMap(params));

        JavaType javaType = this.objectMapper.constructType(BasicFileSearchResult.class);
        return this.get(url, parameters, null, true, javaType);
    }

    /**
     * https://pan.baidu.com/union/document/basic#文件操作
     * 拷贝文件
     * @param params
     * @return
     * @throws BaiduPanSdkException
     */
    public BasicFileManagerResult fileCopy(BasicFileCopyParams params) throws BaiduPanSdkException {
        String url = this.baiduPanApiUrlPrefix + "/xpan/file";
        Map<String, String> parameters = new LinkedHashMap<>();
        parameters.put("method", "filemanager");
        parameters.put("opera", "copy");

        if (params.getAsync() == null) {
            throw new IllegalArgumentException("参数 async 不能为空");
        }

        Map<String, String> formDatas = new LinkedHashMap<>(2);
        formDatas.put("async", params.getAsync() + "");
        try {
            formDatas.put("filelist", objectMapper.writeValueAsString(params.getFilelist()));
        } catch (JsonProcessingException e) {
            throw new BaiduPanSdkException("json 序列化失败", e);
        }

        JavaType javaType = this.objectMapper.constructType(BasicFileManagerResult.class);
        return this.postFormData(url, parameters, null, formDatas, true, javaType);
    }

    /**
     * https://pan.baidu.com/union/document/basic#文件操作
     * 移动文件
     * @param params
     * @return
     * @throws BaiduPanSdkException
     */
    public BasicFileManagerResult fileMove(BasicFileMoveParams params) throws BaiduPanSdkException {
        String url = this.baiduPanApiUrlPrefix + "/xpan/file";
        Map<String, String> parameters = new LinkedHashMap<>();
        parameters.put("method", "filemanager");
        parameters.put("opera", "move");

        if (params.getAsync() == null) {
            throw new IllegalArgumentException("参数 async 不能为空");
        }

        Map<String, String> formDatas = new LinkedHashMap<>(2);
        formDatas.put("async", params.getAsync() + "");
        try {
            formDatas.put("filelist", objectMapper.writeValueAsString(params.getFilelist()));
        } catch (JsonProcessingException e) {
            throw new BaiduPanSdkException("json 序列化失败", e);
        }

        JavaType javaType = this.objectMapper.constructType(BasicFileManagerResult.class);
        return this.postFormData(url, parameters, null, formDatas, true, javaType);
    }

    /**
     * https://pan.baidu.com/union/document/basic#文件操作
     * 重命名文件
     * @param params
     * @return
     * @throws BaiduPanSdkException
     */
    public BasicFileManagerResult fileRename(BasicFileRenameParams params) throws BaiduPanSdkException {
        String url = this.baiduPanApiUrlPrefix + "/xpan/file";
        Map<String, String> parameters = new LinkedHashMap<>();
        parameters.put("method", "filemanager");
        parameters.put("opera", "rename");

        if (params.getAsync() == null) {
            throw new IllegalArgumentException("参数 async 不能为空");
        }

        Map<String, String> formDatas = new LinkedHashMap<>(2);
        formDatas.put("async", params.getAsync() + "");
        try {
            formDatas.put("filelist", objectMapper.writeValueAsString(params.getFilelist()));
        } catch (JsonProcessingException e) {
            throw new BaiduPanSdkException("json 序列化失败", e);
        }

        JavaType javaType = this.objectMapper.constructType(BasicFileManagerResult.class);
        return this.postFormData(url, parameters, null, formDatas, true, javaType);
    }

    /**
     * https://pan.baidu.com/union/document/basic#文件操作
     * 删除文件
     * @param params
     * @return
     * @throws BaiduPanSdkException
     */
    public BasicFileManagerResult fileDelete(BasicFileDeleteParams params) throws BaiduPanSdkException {
        String url = this.baiduPanApiUrlPrefix + "/xpan/file";
        Map<String, String> parameters = new LinkedHashMap<>();
        parameters.put("method", "filemanager");
        parameters.put("opera", "delete");

        if (params.getAsync() == null) {
            throw new IllegalArgumentException("参数 async 不能为空");
        }

        Map<String, String> headers = new LinkedHashMap<>();
        headers.put("User-Agent", "pan.baidu.com");

        Map<String, String> formDatas = new LinkedHashMap<>(2);
        formDatas.put("async", params.getAsync() + "");
        try {
            formDatas.put("filelist", objectMapper.writeValueAsString(params.getFilelist()));
        } catch (JsonProcessingException e) {
            throw new BaiduPanSdkException("json 序列化失败", e);
        }

        JavaType javaType = this.objectMapper.constructType(BasicFileManagerResult.class);
        return this.postFormData(url, parameters, headers, formDatas, true, javaType);
    }

    /**
     * https://pan.baidu.com/union/document/basic#查询文件信息
     * 查询文件信息
     * @param params
     * @return
     */
    public BasicFileMetasResult fileMetas(BasicFileMetasParams params) throws BaiduPanSdkException {
        String url = this.baiduPanApiUrlPrefix + "/xpan/multimedia";
        Map<String, String> parameters = new LinkedHashMap<>();
        parameters.put("method", "filemetas");

        if (params.getFsids() == null) {
            throw new IllegalArgumentException("参数 fsids 不能为空");
        }

        parameters.putAll(beanToMap(params));

        JavaType javaType = this.objectMapper.constructType(BasicFileMetasResult.class);


        BasicFileMetasResult result = this.get(url, parameters, null, true, javaType);


        for (BaiduPanFile baiduPanFile : result.getList()) {
            if (!StringUtils.isEmpty(baiduPanFile.getDlink())) {
                baiduPanFile.setDlink(baiduPanFile.getDlink() + "&access_token=" + tokenStorage.get(baiduPanConfiguration.getApiKey()).getAccessToken());
            }
        }

        return result;
    }
}
